import idraw.*;
import geometry.*;
import tester.*;
import tester.cobertura.Instrument;
import java.util.*;
import colors.*;

@Instrument
@Example
class Examples{
  /**
   * Constructor.
   */
  Examples(){}
  
  // Initial World
  WholeGameWorld myInitialWorld = 
    new WholeGameWorld(new Mfmwg (new Posn(100, 100), 500), 
                       new ConsLoS (new Star (10, new Posn(20, 20)),
                                    new ConsLoS(new Star(15, new Posn(30, 30)),
                                                new ConsLoS(new Star
                                                            (10, new Posn(50, 50)),
                                                            new MtLoS()))));
  
  /**
   * The Go Method.
   */
  void go(){
    this.myInitialWorld.bigBang(200, 300, 0.1);
  }    
  
  /**
   * Main Method
   * @param argv
   */
  public static void main(String[] argv){
    // Construct an instance of a World
    Examples w = new Examples();
    // And run the World
    w.go();
  }
  
  Star star1, star2, star3, star4;
  Mfmwg m, genie1;
  MtLoS mt;
  ConsLoS starList, starList2, starList3, starList4;
  
  /**
   * Initializes or resets the test data to what we want.
   */
  void initData(){
    star1 = new Star(10, new Posn(5,5));
    star2 = new Star(0, new Posn(10,10));
    star3 = new Star(10, new Posn(100, 300));
    star4 = new Star(10, new Posn(50, 50));
    
    m = new Mfmwg(new Posn(50, 50), 50);
    genie1 = new Mfmwg(new Posn(60, 60), 0);
    
    mt = new MtLoS();
    
    starList = new ConsLoS(star1, mt);
    starList2 = new ConsLoS(star2, starList);
    starList3 = new ConsLoS(star3, starList2);
    starList4 = new ConsLoS(star4, starList3);
  }
  
  /**
   * Tests for the hitGroundp method in the Star class.
   * @param t
   */
  @TestMethod
  void testHitGroundp(Tester t){
    initData();
    t.checkExpect(this.star1.hitGroundp(), false);
    t.checkExpect(this.star3.hitGroundp(), true);
    initData();
  }
  
  /**
   * Tests the isFoundp and foundStar methods in the star class 
   * and the ConsLoS class..
   * @param t
   */
  @TestMethod
  void testFound(Tester t){
    initData();
    t.checkExpect(star4.isFoundp(m), true);
    t.checkExpect(star4.isFoundp(genie1), false);
    t.checkExpect(starList4.foundStar(m), true);
    t.checkExpect(starList4.foundStar(genie1), false);
    initData();
  }
  
  /**
   * Tests the caughtStar method in the ConsLoS class.
   * @param t
   */
  @TestMethod
  void testCaughtStar(Tester t){
    initData();
    t.checkExpect(starList4.caughtStar(m), star4);
    initData();
  }
  
  /**
   * Tests the catchStar method in the Mfmwg class.
   * @param t
   */
  @TestMethod
  void testCatchStar(Tester t){
    initData();
    t.checkExpect(m.catchStar(star1), new Mfmwg(m.location, m.fuel + 10));
    initData();
  }  
  
  /**
   * tests the method onTick in all classes that implement it
   * star, world, conslos, genie
   * @param t
   */
  @TestMethod
  void testOnTick(Tester t){
    initData();
    mt.onTick(m);
    t.checkExpect(mt, new MtLoS());
    m.onTick();
    t.checkExpect(m, new Mfmwg(m.location, 45));
    starList.onTick(m);
    t.checkExpect(starList, new ConsLoS(new Star(9, new Posn(5, 13)), new MtLoS()));
    myInitialWorld.onTick();
    t.checkExpect(myInitialWorld,
                  new WholeGameWorld(new Mfmwg (new Posn(100, 100), 495),
                                     new ConsLoS (new Star (9, new Posn(20, 28)),
                                                  new ConsLoS(new Star(14, new Posn(30, 38)),
                                                              new ConsLoS(new Star (9, new Posn(50, 58)),
                                                                          new MtLoS())))));
    initData();  
  }
  
  /**
   * tests the onKeyEvent method in the classes WholeGameWorld and Mfmwg.
   * @param t
   */
  @TestMethod
  void testOnKeyEvent(Tester t){
    initData();
    // Tests:
    myInitialWorld.onKeyEvent("up");
    t.checkExpect(myInitialWorld,
                  new WholeGameWorld(new Mfmwg(new Posn(100, 90), 495),
                                     myInitialWorld.stars));
    myInitialWorld.onKeyEvent("down");
    t.checkExpect(myInitialWorld,
                  new WholeGameWorld(new Mfmwg(new Posn(100, 100), 495),
                                     myInitialWorld.stars));
    myInitialWorld.onKeyEvent("left");
    t.checkExpect(myInitialWorld,
                  new WholeGameWorld(new Mfmwg(new Posn(90, 100), 495),
                                     myInitialWorld.stars));
    myInitialWorld.onKeyEvent("right");
    t.checkExpect(myInitialWorld,
                  new WholeGameWorld(new Mfmwg(new Posn(100, 100), 495),
                                     myInitialWorld.stars));   
    genie1.onKeyEvent("right");
    t.checkExpect(genie1, new Mfmwg(new Posn(70, 60), 0));
    genie1.onKeyEvent("left");
    t.checkExpect(genie1, new Mfmwg(new Posn(60, 60), 0));
    genie1.onKeyEvent("up");
    t.checkExpect(genie1, new Mfmwg(new Posn(60, 50), 0));
    genie1.onKeyEvent("down");
    t.checkExpect(genie1, new Mfmwg(new Posn(60, 60), 0));
    initData();
  }
  
  /**
   * Tests the makeStar event in the Star class.
   * @param t
   */
  @TestMethod
  void testMakeStar(Tester t){
    initData();
    // Tests:
    t.checkNumRange(star1.makeStar().location.x, 0, 200);
    t.checkExpect(star1.makeStar().location.y, 5);
    t.checkNumRange(star1.makeStar().span, 0, 35);
    initData();
  }
}
